package com.ruoyi.common.utils;

import java.util.Arrays;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * API签名工具类
 *
 * @author ruoyi
 */
public class ApiSignatureUtils {
    private static final Logger log = LoggerFactory.getLogger(ApiSignatureUtils.class);


    // 默认签名方法
    private static final String DEFAULT_SIGN_METHOD = "HmacSHA256";
    // 模拟的API密钥，实际应该从数据库或配置文件中获取
    private static final String SECRET_KEY = "rc-api-secret-key";


    public static String convertParamsToString(Map<String, String> params) {
        // 将参数按key的ASCII码升序排序
        Map<String, String> sortedParams = new TreeMap<>(params);

        // 构造待签名字符串
        StringBuilder sb = new StringBuilder();
        Set<Map.Entry<String, String>> entries = sortedParams.entrySet();
        for (Map.Entry<String, String> entry : entries) {
            if (StringUtils.isNotEmpty(entry.getValue())) {
                sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
            }
        }

        // 删除最后一个&
        if (sb.length() > 0) {
            sb.deleteCharAt(sb.length() - 1);
        }
        return sb.toString();
    }


    /**
     * 生成签名
     *
     * @param params 参数集合
     * @param userId 用户的id
     * @return 签名字符串
     */
    public static String generateSignature(Map<String, String> params, String userId) {
        String sb = convertParamsToString(params);
        // 加上密钥
        String signStr = sb + SECRET_KEY + userId;
        log.info("sb:{},secretKey:{}", sb, SECRET_KEY);
        // 使用指定算法生成签名
        return encrypt(signStr);
    }

    /**
     * 验证签名
     *
     * @param params 参数集合
     * @param sign   待验证的签名
     * @return 是否验证通过
     */
    public static boolean verifySignature(Map<String, String> params, String userId, String sign) {
        // 生成签名
        String generatedSign = generateSignature(params, userId);

        // 比较签名
        return generatedSign.equals(sign);
    }

    /**
     * 使用HmacSHA256算法加密
     *
     * @param content 待加密内容
     * @return 加密后的字符串
     */
    public static String encrypt(String content) {
        try {
            Mac mac = Mac.getInstance(DEFAULT_SIGN_METHOD);
            SecretKeySpec secretKeySpec = new SecretKeySpec(SECRET_KEY.getBytes("UTF-8"), DEFAULT_SIGN_METHOD);
            mac.init(secretKeySpec);
            byte[] hash = mac.doFinal(content.getBytes("UTF-8"));
            return Hex.encodeHexString(hash).toUpperCase();
        } catch (Exception e) {
            throw new RuntimeException("签名生成失败", e);
        }
    }

    /**
     * 获取需要签名的参数
     *
     * @param params 所有参数
     * @return 需要签名的参数
     */
    public static Map<String, String> getSignParams(Map<String, String[]> params) {
        Map<String, String> signParams = new TreeMap<>();
        Set<Map.Entry<String, String[]>> entries = params.entrySet();
        for (Map.Entry<String, String[]> entry : entries) {
            String[] values = entry.getValue();
            if (values != null && values.length > 0) {
                // 如果有多个值，只取第一个
                signParams.put(entry.getKey(), values[0]);
            }
        }
        return signParams;
    }
}